package Core;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;

public class CharacterClassImpl implements CharacterClass {
	private Map<Integer, List<ClassRequirement>> _levelRequirements;
	private Map<Integer, LevelSnapshot> _levelSnapshots;
	private String _name;
	
	public CharacterClassImpl()
	{
		this._levelRequirements = new HashMap<Integer, List<ClassRequirement>>();
		this._levelSnapshots = new HashMap<Integer, LevelSnapshot>();
	}
	
	@Override
	public String getName()
	{
		return this._name;
	}
	
	@Override
	public void setName(String name)
	{
		this._name = name;
	}
	
	@Override
	public Map<Integer, List<ClassRequirement>> getAllRequirements()
	{
		return this._levelRequirements;
	}
	
	@Override
	public List<ClassRequirement> getRequirementsForLevel(int level)
	{
		return this._levelRequirements.get(level);
	}
	
	@Override 
	public void addRequirement(int level, ClassRequirement newRequirement)
	{
		this.addLevelToRequirementIfDoesntExist(level);
		
		List<ClassRequirement> requirements = this.getRequirementsForLevel(level);
		
		requirements.add(newRequirement);
	}
	
	@Override
	public void addEmptyRequirements(int level)
	{
		this.addLevelToRequirementIfDoesntExist(level);
	}
	
	private void addLevelToRequirementIfDoesntExist(int level)
	{
		if(!this.checkForRequirements(level))
		{
			this._levelRequirements.put(level, new ArrayList<ClassRequirement>());
		}
	}
	
	@Override
	public boolean canLevel(Character character, int level)
	{
		boolean canLevel = true;
		
		if ((!this.checkForSnapshot(level)) ||
			(!this.checkForRequirements(level)) ||
			(!this.checkIfCharacterSatisfiesRequirements(character, level)))
		{
			canLevel = false;
		}
		
		return canLevel;
	}

	private boolean checkForSnapshot(int level)
	{
		boolean hasSnapshot;
		
		hasSnapshot = this._levelSnapshots.containsKey(level);
		
		return hasSnapshot;
	}
	
	private boolean checkForRequirements(int level)
	{
		boolean hasRequirements;
		
		hasRequirements = this._levelRequirements.containsKey(level);
		
		return hasRequirements;
	}
	
	private boolean checkIfCharacterSatisfiesRequirements(Character character, int level)
	{
		boolean satisfiesRequirements = true;
		
		List<ClassRequirement> requirements = this.getRequirementsForLevel(level);
		
		for	(ListIterator<ClassRequirement> it = requirements.listIterator(); it.hasNext(); )
		{
			ClassRequirement current = it.next();

			if (!current.isSatisfiedBy(character))
			{
				satisfiesRequirements = false;
			}
		}
		
		return satisfiesRequirements;
	}
	
	@Override
	public boolean equivalentTo(CharacterClass otherClass)
	{
		// this logic should probably be moved to an external comparer class
		return this.getName() == otherClass.getName();
	}
	
	@Override
	public void addLevelSnapshot(int level, LevelSnapshot snapshot)
	{
		this._levelSnapshots.put(level, snapshot);
	}
	
	@Override
	public LevelSnapshot findSnapshotByLevel(int level)
	{
		return this._levelSnapshots.get(level);
	}
	
	
}
